Register Variables (for both Pascal and C programmers)

If you take a look at TestCignal.c, the C version of the signal-testing MPW tool,
you will note the following code in main():

	volatile long		registerLong = 0;
	
	InitUFailure();

	if (code = CatchSignal()) {
		fprintf(stdout, "Signal caught in main; code = %d, (registerLong = %d)\n",
			code, registerLong);
		return 0;
	}
	
	registerLong = 0xffff;
	
	Signal(Value());

The storage specifier volatile is used in the declaration of registerLong because
of a potential problem with the value of register variables at the point of the
CatchSignal(). This problem can occur when using longjmp() as well.

What happens is that the compiler (being a clever little fellow) decides that a
local scalar variable can be conveniently kept in a register. When the exception is
raised, all non-scratch registers are restored to what they were before the
CatchSignal() call. If registerLong is kept in D3, for instance, then it will have
the value 0 instead of 0xffff while processing the exception.

This can be a serious problem if the register variable holds something like a
handle or pointer, since you are likely to want to dispose of the block that it
references if an exception occurs.

In C this potential difficulty can be avoided by declaring a variable volatile. The
compiler will keep a local variable on the stack and not leave it in a register. So,
the printf() displays the correct value of 65535. If you removed the volatile
storage specifier, 0 would be value of registerLong when printf() was called. If there
is any doubt about a variable in your C program, be volatile.


In the Pascal TestSignal tool in Main:

		registerLong:	LONGINT;

	BEGIN
{InitSignals has already been done}
		registerLong := 0;
		
		{catch Signals not otherwise caught by the program}
		code := CatchSignal;
		IF code <> 0 THEN BEGIN
			NumToString(code, aString);
			aString := Concat('Signal caught from main, code = ',aString,
				', registerLong = ');
			DoCatchOutMain(aString, registerLong);
		END;
		
		registerLong := $FFFF;
		
		Signal(Value);


The Pascal tool displays zero for the value of registerLong since the compiler keeps
it in a D register. This means that you must be careful in your use of local variables
when CatchSignal is involved. This is never a problem when using CatchFailures since
the handler is a separate procedure and any locals of an enclosing procedure would be
pulled off the stack by the handler.

Apple is investigating ways to get the same kind of control in Pascal that the
volatile storage specifier gives you in C. A future version of MPW Pascal will almost
certainly have this capability.